/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "PictureFormat.h"
#include <ColorPacked.h>

namespace liba
{
namespace pictureformat
{

inline const void * RGBConverter<A8R8G8B8>::from(ColorPacked * color, const void * src)
{
	const unsigned char * pixel = static_cast<const unsigned char *>( src );
	color->b = *pixel++;
	color->g = *pixel++;
	color->r = *pixel++;
	color->a = *pixel++;
	return pixel;
}
inline void * RGBConverter<A8R8G8B8>::to(const ColorPacked * color, void * dst)
{
	unsigned char * pixel = static_cast<unsigned char *>( dst );
	*pixel++ = color->b;
	*pixel++ = color->g;
	*pixel++ = color->r;
	*pixel++ = color->a;
	return pixel;
}

inline const void * RGBConverter<R8G8B8A8>::from(ColorPacked * color, const void * src)
{
	const unsigned char * pixel = static_cast<const unsigned char *>( src );
	color->r = *pixel++;
	color->g = *pixel++;
	color->b = *pixel++;
	color->a = *pixel++;
	return pixel;
}
inline void * RGBConverter<R8G8B8A8>::to(const ColorPacked * color, void * dst)
{
	unsigned char * pixel = static_cast<unsigned char *>( dst );
	*pixel++ = color->r;
	*pixel++ = color->g;
	*pixel++ = color->b;
	*pixel++ = color->a;
	return pixel;
}

inline const void * RGBConverter<R8G8B8>::from(ColorPacked * color, const void * src)
{
	const unsigned char * pixel = static_cast<const unsigned char *>( src );
	color->r = *pixel++;
	color->g = *pixel++;
	color->b = *pixel++;
	color->a = 255;
	return pixel;
}
inline void * RGBConverter<R8G8B8>::to(const ColorPacked * color, void * dst)
{
	unsigned char * pixel = static_cast<unsigned char *>( dst );
	*pixel++ = color->r;
	*pixel++ = color->g;
	*pixel++ = color->b;
	return pixel;
}

inline const void * RGBConverter<B8G8R8>::from(ColorPacked * color, const void * src)
{
	const unsigned char * pixel = static_cast<const unsigned char *>( src );
	color->b = *pixel++;
	color->g = *pixel++;
	color->r = *pixel++;	
	color->a = 255;
	return pixel;
}
inline void * RGBConverter<B8G8R8>::to(const ColorPacked * color, void * dst)
{
	unsigned char * pixel = static_cast<unsigned char *>( dst );
	*pixel++ = color->b;
	*pixel++ = color->g;	
	*pixel++ = color->r;
	return pixel;
}

inline const void * RGBConverter<R8G8B8CK>::from(ColorPacked * color, const void * src)
{
	const unsigned char * pixel = static_cast<const unsigned char *>( src );
	color->b = *pixel++;
	color->g = *pixel++;
	color->r = *pixel++;
	if( color->r == colorkey_red && color->g == colorkey_green && color->b == colorkey_blue )
		color->a = 0;
	else
		color->a = 255;
	return pixel;
}
inline void * RGBConverter<R8G8B8CK>::to(const ColorPacked * color, void * dst)
{
	unsigned char * pixel = static_cast<unsigned char *>( dst );
	if( IsAlphaTransparent(color->a) )
	{
		*pixel++ = colorkey_blue;
		*pixel++ = colorkey_green;
		*pixel++ = colorkey_red;
	}
	else
	{
		if( color->r == colorkey_red && color->g == colorkey_green && color->b == colorkey_blue )
		{
			*pixel++ = colorkey_blue_near;
			*pixel++ = colorkey_green_near;
			*pixel++ = colorkey_red_near;
		}
		else
		{
			*pixel++ = color->b;
			*pixel++ = color->g;
			*pixel++ = color->r;
		}
	}
	return pixel;
}

inline const void * RGBConverter<R5G6B5>::from(ColorPacked * color, const void * src)
{
	const unsigned short * pixel = static_cast<const unsigned short *>( src );
	color->b = (*pixel & 0x001F) << 3;
	color->g = (*pixel & 0x07E0) >> 3;
	color->r = (*pixel & 0xF800) >> 8;
	color->a = 255;
	return pixel + 1;
}
inline void * RGBConverter<R5G6B5>::to(const ColorPacked * color, void * dst)
{
	unsigned short * pixel = static_cast<unsigned short *>( dst );
	*pixel = (color->b >> 3) + ((color->g & 0xFC) << 3) + ((color->r & 0xF8) << 8);
	return pixel + 1;
}

inline const void * RGBConverter<A1R5G5B5>::from(ColorPacked * color, const void * src)
{
	const unsigned short * pixel = static_cast<const unsigned short *>( src );
	color->b = (*pixel & 0x001F) << 3;
	color->g = (*pixel & 0x03E0) >> 2;
	color->r = (*pixel & 0x7C00) >> 7;
	color->a = (*pixel & 0x8000) ? 255 : 0;
	return pixel + 1;
}
inline void * RGBConverter<A1R5G5B5>::to(const ColorPacked * color, void * dst)
{
	unsigned short * pixel = static_cast<unsigned short *>( dst );
	unsigned short value = (color->b >> 3) + ((color->g & 0xF8) << 2) + ((color->r & 0xF8) << 7);
	if( IsAlphaTransparent(color->a) )
		value += 0x8000;
	*pixel = value;
	return pixel + 1;
}

inline const void * RGBConverter<A4R4G4B4>::from(ColorPacked * color, const void * src)
{
	const unsigned short * pixel = static_cast<const unsigned short *>( src );
	color->b = (*pixel & 0x000F) << 4;
	color->g = (*pixel & 0x00F0);
	color->r = (*pixel & 0x0F00) >> 4;
	color->a = (*pixel & 0xF000) >> 8;
	return pixel + 1;
}
inline void * RGBConverter<A4R4G4B4>::to(const ColorPacked * color, void * dst)
{
	unsigned short * pixel = static_cast<unsigned short *>( dst );
	*pixel = (color->b >> 4) + ((color->g & 0xF0)) + ((color->r & 0xF0) << 4) + ((color->a & 0xF0) << 8);
	return pixel + 1;
}

inline const void * RGBConverter<R5G6B5CK>::from(ColorPacked * color, const void * src)
{
	const unsigned short * pixel = static_cast<const unsigned short *>( src );
	color->b = (*pixel & 0x001F) << 3;
	color->g = (*pixel & 0x07E0) >> 3;
	color->r = (*pixel & 0xF800) >> 8;
	if( *pixel == colorkey_short )
		color->a = 0;
	else
		color->a = 255;
	return pixel + 1;
}
inline void * RGBConverter<R5G6B5CK>::to(const ColorPacked * color, void * dst)
{
	unsigned short * pixel = static_cast<unsigned short *>( dst );
	if( IsAlphaTransparent( color->a ) )
		*pixel = colorkey_short;
	else
	{
		unsigned short value = (color->b >> 3) + ((color->g & 0xFC) << 3) + ((color->r & 0xF8) << 8);
		if( value == colorkey_short )
			*pixel = colorkey_short_near;
		else
			*pixel = value;
	}
	return pixel + 1;
}

} // namespace pictureformat
} // namespace liba